// Copyright (c) 2021 Presto Labs Pte. Ltd.
// Author: hyuan

#include "coin2/exchange/phemex/api_order/native_rest_async_asio_subscriber.h"

namespace coin2::exchange::phemex::api_order {

void PhemexRestAsyncAsioSubscriber::QueryBalance() {
  RestParams params;
  auto http_context = rest_client()->QueryAccountBalance(params);
  if (!http_context) return;
  http_context->handler =
      std::bind(&PhemexRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void PhemexRestAsyncAsioSubscriber::QueryOpenOrders(const std::string& native_symbol) {
  RestParams params;
  params.set_symbol(native_symbol);
  auto http_context = rest_client()->QueryOpenOrders(params);
  if (!http_context) return;
  http_context->handler =
      std::bind(&PhemexRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void PhemexRestAsyncAsioSubscriber::QueryHistoryOrders(const std::string& native_symbol) {
  RestParams params;
  params.set_symbol(native_symbol);
  auto http_context = rest_client()->QueryHistoryOrders(params);
  if (!http_context) return;
  http_context->handler =
      std::bind(&PhemexRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void PhemexRestAsyncAsioSubscriber::QueryFills(const std::string& native_symbol) {
  RestParams params;
  params.set_symbol(native_symbol);
  auto http_context = rest_client()->QueryFills(params);
  if (!http_context) return;
  http_context->handler =
      std::bind(&PhemexRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void PhemexRestAsyncAsioSubscriber::QueryWithdrawAndDeposit() {
  RestParams params;
  auto http_context = rest_client()->QueryDeposit(params);
  if (!http_context) return;
  http_context->handler =
      std::bind(&PhemexRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);

  http_context = rest_client()->QueryWithdraw(params);
  if (!http_context) return;
  http_context->handler =
      std::bind(&PhemexRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void PhemexRestAsyncAsioSubscriber::QueryTransfer(const std::string& ccy) {
  RestParams params;
  params.set_currency(ccy);
  auto http_context = rest_client()->QuerySpotAccountTransfer(params);
  if (!http_context) return;
  http_context->handler =
      std::bind(&PhemexRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);

  http_context = rest_client()->QueryFuturesAccountTransfer(params);
  if (!http_context) return;
  http_context->handler =
      std::bind(&PhemexRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void PhemexRestAsyncAsioSubscriber::SubscribeAsync() {
  AddPeriodicTask(
      std::bind(&PhemexRestAsyncAsioSubscriber::QueryBalance, this),
      config_.query_account_balance_period_sec(),
      "query_balance");

  auto symbol_list = native_symbols();

  if (is_readonly_order_system_ && symcache_->is_spot()) {
    const auto& currency_list = rest_client()->GetTransferCurrencyList();
    AddPeriodicTask(
        std::bind(&PhemexRestAsyncAsioSubscriber::QueryTransfer, this, std::placeholders::_1),
        config_.query_account_balance_period_sec(),
        "query_transfer",
        currency_list);

    AddPeriodicTask(
        std::bind(&PhemexRestAsyncAsioSubscriber::QueryWithdrawAndDeposit, this),
        config_.query_account_balance_period_sec(),
        "query_withdraw_and_deposit",
        currency_list);
  }

  AddPeriodicTask(
      std::bind(&PhemexRestAsyncAsioSubscriber::QueryOpenOrders, this, std::placeholders::_1),
      config_.query_open_orders_period_sec(),
      "query_open_orders",
      symbol_list);

  AddPeriodicTask(
      std::bind(&PhemexRestAsyncAsioSubscriber::QueryHistoryOrders, this, std::placeholders::_1),
      std::bind(
          &PhemexRestAsyncAsioSubscriber::SkipQuery,
          this,
          "query_history_orders",
          std::placeholders::_1),
      config_.query_cancel_orders_period_sec(),
      "query_history_orders",
      symbol_list);

  AddPeriodicTask(
      std::bind(&PhemexRestAsyncAsioSubscriber::QueryFills, this, std::placeholders::_1),
      std::bind(
          &PhemexRestAsyncAsioSubscriber::SkipQuery,
          this,
          "query_fills",
          std::placeholders::_1),
      config_.query_fill_period_sec(),
      "query_fills",
      symbol_list);
}

}  // namespace coin2::exchange::phemex::api_order
